package xdu.lz.stage6_threadpool.chapter2_excutors_threadPoolImpl;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created at 2019/10/23 0023 下午 9:54
 * --
 */
public class SingleThreadPool {

    /**
     * coreSize = MaxSize = 1;
     * keepAliveTime = 0 ，因为Idel中 maxSize ！> coreSize 所以不会回收
     * blockingQueue = LinkedBlockingQueue,给了默认构造函数个数Integer.MAX_VALUE
     * threadFactory = Executors.defaultThreadFactory implements ThreadFactory interface
     * <p>
     *
     * 注意类型，不是ThreadPoolExecutor,强转会失败
     * public static ExecutorService newSingleThreadExecutor() {
     *  return new FinalizableDelegatedExecutorService
     *      (new ThreadPoolExecutor(1, 1,
     *          0L, TimeUnit.MILLISECONDS,
     *          new LinkedBlockingQueue<Runnable>()));
     * }
     * FinalizableDelegatedExecutorService extends DelegatedExecutorService extends AbstractExecutorService
     * FinalizableDelegatedExecutorService没有API，
     * 而DelegatedExecutorService所有的API都是AbstractExecutorService的API
     *
     *也就是说这个内部包装类 ，不允许我们配置SingleThread。但是newFixed(1)可以配置通过API配置一些参数。
     *
     * 创建一个单线程的线程池。这个线程池只有一个线程在工作，也就是相当于单线程串行执行所有任务。
     * 如果这个唯一的线程因为异常结束，那么会有一个新的线程来替代它。
     * 此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
     *
     * <p>
     * 不会自动关闭
     *
     * @return
     */
    private static ExecutorService newSingleThreadExecutor
            () {

        AtomicInteger counter = new AtomicInteger();
        ExecutorService executor = Executors.newSingleThreadExecutor();

        for (int i = 0; i < 50; i++) {
            executor.execute(() -> {

                if(counter.getAndIncrement() % 10 == 0){
                    throw new RuntimeException("");
                }
                try {
                    Thread.sleep(20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread()+" === :"+counter.get());
            });
        }

        return executor;
    }

    public static void main(String[] args) throws InterruptedException {
        newSingleThreadExecutor();
        Thread.sleep(1000);
        newFixedThreadPool(1);
    }


    private static ExecutorService newFixedThreadPool(int n) {
        ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(n);
        AtomicInteger counter = new AtomicInteger();
        for (int i = 0; i < 50; i++) {
            executor.execute(() -> {
                System.out.println(Thread.currentThread()+" === :"+counter.get());
                if(counter.getAndIncrement() % 10 == 0){
                    throw new RuntimeException("");
                }
                try {
                    Thread.sleep(20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        return executor;
    }
}
